package com.eolcum.evo.thread;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import android.content.Context;
import android.util.Base64;
import android.util.Log;

import com.eolcum.evo.persistence.Apartment;
import com.eolcum.evo.persistence.DataBaseHelper;
import com.eolcum.evo.persistence.Sensor;
import com.eolcum.rest.dto.Action;
import com.eolcum.rest.dto.GetApartmentInfoDTO;
import com.eolcum.rest.dto.PollDTO;
import com.google.gson.Gson;

public class CommunicationManager implements Runnable {
	private Context context;
	private Apartment apartment;
	private DataBaseHelper dbHelper;
	
	private String evoCenterToken = null;
	private final String loginServiceEndpoint = "/loginService/login";
	private final String pollingServiceEndpoint = "/pollingService/poll";
	final String USER_AGENT = "Mozilla/5.0";
	private final String endpoint = "http://192.168.1.57:9091";
	
	@Override
	public void run() {
		long cycleFrequency = 1000L;

		while (true) {
			try {
				if (evoCenterToken == null)
					login();
				else {
					URL obj = new URL(endpoint + pollingServiceEndpoint);

					HttpURLConnection con = (HttpURLConnection) obj
							.openConnection();
					// add request header
					con.setRequestProperty("User-Agent", USER_AGENT);
					con.setRequestProperty("Authorization", evoCenterToken);
					con.setRequestProperty("Content-Type", "application/json");
					con.setRequestMethod("POST");
					con.setDoOutput(true);
					con.setDoInput(true);
					OutputStreamWriter wr= new OutputStreamWriter(con.getOutputStream());
					wr.write("1");
					wr.flush();

					int responseCode = con.getResponseCode();
					if(responseCode != HttpURLConnection.HTTP_OK) {
						BufferedReader in = new BufferedReader(
								new InputStreamReader(con.getErrorStream()));
						String inputLine;
						StringBuffer responseBfr = new StringBuffer();

						while ((inputLine = in.readLine()) != null) {
							responseBfr.append(inputLine);
						}
						in.close();
						Log.e("CommunicationManagerThread",
								"\nSending 'GET' request to URL : " + endpoint + pollingServiceEndpoint + " " + responseBfr.toString());

					}

					Log.i("CommunicationManagerThread",
							"\nSending 'GET' request to URL : " + endpoint + pollingServiceEndpoint);
					Log.i("CommunicationManagerThread", "Response Code : "
							+ responseCode);

					BufferedReader in = new BufferedReader(
							new InputStreamReader(con.getInputStream()));
					String inputLine;
					StringBuffer responseBfr = new StringBuffer();

					while ((inputLine = in.readLine()) != null) {
						responseBfr.append(inputLine);
					}
					in.close();

					// print result
					Log.i("CommunicationManagerThread", responseBfr.toString());
					Gson gson = new Gson();
					PollDTO pollDTO = gson.fromJson(
							responseBfr.toString(), PollDTO.class);
					if (pollDTO.getFrequency() != null)
						cycleFrequency = pollDTO.getFrequency();
					if (pollDTO.getActionList() != null) {
						for (int i = 0; i < pollDTO.getActionList().size(); i++) {
							switch (pollDTO.getActionList().get(i).getAction()) {
							case Action.ACTION_GET_APARTMENT_INFO:
								callGetAparmentInfo(pollDTO.getActionList().get(i));
								break;
							case Action.ACTION_GET_YESTERDAY_SENSOR_LOG:
								callGetYesterdaySensorLog(pollDTO.getActionList().get(i));
							}

						}
					}
				}
				Thread.currentThread();
				Thread.sleep(cycleFrequency);

			} catch (MalformedURLException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

	}

	private void login() throws IOException {

		URL obj = new URL(endpoint + loginServiceEndpoint);

		HttpURLConnection con = (HttpURLConnection) obj.openConnection();
		// add request header
		con.setRequestProperty("User-Agent", USER_AGENT);
		con.setRequestProperty(
				"Authorization",
				"Basic "
						+ Base64.encodeToString("EXT0289606:abc".getBytes(),
								Base64.DEFAULT));
		con.setRequestProperty("Content-Type", "application/json");
		int responseCode = con.getResponseCode();

		Log.i("CommunicationManagerThread", "\nSending 'GET' request to URL : "
				+ loginServiceEndpoint);
		Log.i("CommunicationManagerThread", "Response Code : " + responseCode);

		BufferedReader in = new BufferedReader(new InputStreamReader(
				con.getInputStream()));
		String inputLine;
		StringBuffer response = new StringBuffer();

		while ((inputLine = in.readLine()) != null) {
			response.append(inputLine);
		}
		String authString = con.getHeaderField("Authorization");
		if (authString != null && authString.length() > 0) {
			evoCenterToken = authString;
		}
		in.close();

		// print result
		Log.i("CommunicationManagerThread", response.toString());

	}

	public Context getContext() {
		return context;
	}

	public void setContext(Context context) {
		this.context = context;
	}

	public Apartment getApartment() {
		return apartment;
	}

	public void setApartment(Apartment apartment) {
		this.apartment = apartment;
	}
	
	public void callGetAparmentInfo(Action action) throws IOException {
		StringBuffer responseBfr;
		do {
			Gson gson = new Gson();
			GetApartmentInfoDTO responseDTO = new GetApartmentInfoDTO();
			responseDTO.setApartment(apartment);
			action.setResponseJSON(gson.toJson(responseDTO));
			URL url = new URL(action.getResponseURL());
			HttpURLConnection con = (HttpURLConnection) url.openConnection();
			// add request header
			con.setRequestProperty("User-Agent", USER_AGENT);
			con.setRequestProperty("Authorization", evoCenterToken);
			con.setRequestProperty("Content-Type", "application/json");
			con.setRequestMethod("POST");
			con.setDoOutput(true);
			con.setDoInput(true);
			OutputStreamWriter writer = new OutputStreamWriter(con.getOutputStream());
			writer.write(gson.toJson(action));
			writer.flush();
			int responseCode = con.getResponseCode();

			Log.i("CommunicationManagerThread",
					"\nSending 'GET' request to URL : " + action.getResponseURL());
			Log.i("CommunicationManagerThread", "Response Code : "
					+ responseCode);

			BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));

			responseBfr = new StringBuffer();

			String inputLine;
			while ((inputLine = in.readLine()) != null) {
				responseBfr.append(inputLine);
			}
			in.close();
			
			} while(!"OK".equals(responseBfr.toString()));

	}
	private void callGetYesterdaySensorLog(Action action) throws IOException{
		StringBuffer responseBfr;
		do {
			Calendar cal = Calendar.getInstance();
			cal.set(Calendar.HOUR_OF_DAY, 0);
			cal.set(Calendar.MINUTE, 0);
			cal.set(Calendar.SECOND, 0);
			cal.set(Calendar.MILLISECOND, 0);
			long endTime = cal.getTimeInMillis();
			long startTime = endTime - 86399999;
			Gson gson = new Gson();
			List<Sensor> sensorLogList = new ArrayList<Sensor>();
			String serialNo;
			for(int i = 0; i < apartment.getRooms().size(); i++) {
				for(int j = 0; j < apartment.getRooms().get(i).getSensors().size(); j++) {
					serialNo = apartment.getRooms().get(i).getSensors().get(j).getSerialNo();
					int sensorId = apartment.getRooms().get(i).getSensors().get(j).getId();
					List<Sensor> sensors = dbHelper.getSensorHistory("" + sensorId, serialNo, startTime, endTime);
					for(int k = 0; k < sensors.size(); k++) {
						sensorLogList.add(sensors.get(k));
					}
				}
			}
			URL url = new URL(action.getResponseURL());
			HttpURLConnection con = (HttpURLConnection) url.openConnection();
			// add request header
			con.setRequestProperty("User-Agent", USER_AGENT);
			con.setRequestProperty("Authorization", evoCenterToken);
			con.setRequestProperty("Content-Type", "application/json");
			con.setRequestMethod("POST");
			con.setDoOutput(true);
			con.setDoInput(true);
			OutputStreamWriter writer = new OutputStreamWriter(con.getOutputStream());
			writer.write(gson.toJson(sensorLogList));
			writer.flush();
			int responseCode = con.getResponseCode();

			Log.i("CommunicationManagerThread",
					"\nSending 'GET' request to URL : " + action.getResponseURL());
			Log.i("CommunicationManagerThread", "Response Code : "
					+ responseCode);

			BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));

			responseBfr = new StringBuffer();

			String inputLine;
			while ((inputLine = in.readLine()) != null) {
				responseBfr.append(inputLine);
			}
			in.close();
			
			} while(!"OK".equals(responseBfr.toString()));
	}
	public void setDbHelper(DataBaseHelper dbHelper) {
		this.dbHelper = dbHelper;
	}
}